﻿/**
* Manages dynamic sounds
* @author Liam O'Donnell
* @version 0.1
*/
package com.spikything.audio {
	
	//import Utils;
	import com.spikything.audio.SoundItem;
	import com.spikything.audio.AudioEvent;
	import flash.media.SoundChannel;
	import flash.utils.Timer;
	import flash.events.Event;
	import flash.events.TimerEvent;
	import flash.events.MouseEvent;
	import flash.display.Sprite;
	import flash.text.TextField;
	import flash.text.TextFormat;
	
	public class AudioManager extends Sprite {
		
		private const LOOP_CUT 			:Number 	= 15;
		private const CROSSFADE 		:Number 	= 4000;
		private const NUM_ARROW_SOUNDS 	:Number 	= 3;
		
		private var output 				:TextField;
		
		private var soundItems 			:Array;
		
		private var assetPrefix 		:String 	= "sounds/";
		private var assetSuffix 		:String 	= ".mp3";
		
		private var loadList 			:Array;
		private var loadName 			:String;
		private var loadingItem 		:String;
		
		private var otherNames 			:Array 		= ["test"]; // ["global_rollover","section_3_closeup_loop","section_2_closeup_loop","section_1_closeup_loop", "global_transition_to_close_up_Left", "global_transition_to_close_up_Right", "section_2_video_1", "section_2_video_2", "section_2_video_3", "section_3_lane_vibrate", "section_3_road_rumble"]
		
		//"headlight_rollover_1", "wheel_rollover_1", "outline_rollover_1", "engine_rollover_1", "headlight_closeup_loop", "wheel_closeup_loop", "engine_closeup_loop", "outline_closeup_loop", "transition_to_close_up_Left", "transition_to_close_up_Right",  "panel_slide_in", "panel_slide_out";
		
		private var otherItems 			:Array;
		private var padsNames 			:Array 		= []; // ["section_1_bg_pad_1", "section_2_bg_pad_1", "section_3_bg_pad_1", "section_1_bg_pad_2", "section_2_bg_pad_2", "section_3_bg_pad_2", "section_1_bg_pad_3", "section_2_bg_pad_3", "section_3_bg_pad_3", "section_1_bg_pad_4", "section_2_bg_pad_4", "section_3_bg_pad_4", "section_1_bg_pad_5", "section_2_bg_pad_5", "section_3_bg_pad_5", "section_1_bg_pad_6", "section_2_bg_pad_6", "section_3_bg_pad_6"];
		private var padsItems 			:Array;
		
		private var arrowSoundsNames 	:Array 		= []; // ["open_swell_1", "open_swell_2", "open_swell_3", "drum_loop_1", "drum_loop_2", "drum_loop_3", "drum_end_1", "drum_end_2", "drum_end_3"];
		private var arrowSoundsItems 	:Array;
		private var arrowOver 			:Boolean;
		private var arrowSoundIndex 	:Number;
		private var arrowSoundPlaying 	:Boolean;
		private var _mp3offset			:Number
		
		private var _isMuted 			:Boolean;
		public var 	currentSoundScape 	:Number 	= 0;
		private var numPads 			:Number 	= 3;
		private var numSoundScapes 		:Number 	= 3;
		
		//
		public function AudioManager () {
			
			// var someSound:SoundItem = getSound(arrowSoundsNames[0]);
			
			// Add an output field
			output = new TextField();
			output.background = true;
			output.x = 110;
			output.y = 10;
			output.width = output.height = 200;
			output.defaultTextFormat = new TextFormat("_sans", 10);
			// addChild(output);
			
			// Start loading up sounds
			soundItems = new Array();
			//loadItems("other");
			
		}
		
		//
		public function loadItems (what:String):void {
			doOutput("# loadItems: "+what);
			loadName = what;
			loadList = this[loadName+"Names"].concat();
			this[loadName+"Items"] = new Array();
			loadNextItem();
		}
		
		//
		public function loadNextItem ():void {
			if (!loadList.length) {
				itemsLoaded(loadName);
				return;
			}
			loadingItem = loadList.shift();
			this[loadName+"Items"].push(getSound(loadingItem));
		}
		
		//
		public function itemsLoaded (what:String):void {
			doOutput("# itemsLoaded: "+what);
			//if (what=="other") loadItems("arrowSounds");
			//if (what=="arrowSounds") loadItems("pads");
			if (what=="other") loadItems("pads");
			// if (what=="pads") padsItems[0].start(true);
		}
		
		//
		public function getSound (what:String=""):SoundItem {
			var item:SoundItem = new SoundItem(what.length>0 ? assetPrefix + what + assetSuffix : what, what);
			if(what == "section_3_road_rumble") item._MP3OFFSET = 120;
			item.addEventListener(AudioEvent.LOADED, onSoundLoaded);
			item.addEventListener(AudioEvent.FINISHED, onSoundComplete);
			soundItems.push(item);
			return item;
		}
		
		//
		public function playSound (what:String, loop:Boolean=false, offset:Number=0):SoundChannel {
			doOutput("playSound: "+what+" "+loop+" "+offset);
			var s:SoundItem = getInstance(what);
			return s.start(loop, offset); //for each (var s:SoundItem in soundItems) if (s.soundName==what)
			return null;
		}
		//
		public function fadeOut (what:String):void {
			var s:SoundItem = getInstance(what);
			s.fadeOut(); //for each (var s:SoundItem in soundItems) if (s.soundName==what)
		}
		//
		public function fadeIn (what:String, loop:Boolean=false):void {
			var s:SoundItem = getInstance(what);
			s.fadeIn(loop); //for each (var s:SoundItem in soundItems) if (s.soundName==what)
		}
		
		//
		public function getInstance (what:String):SoundItem {
			for each (var s:SoundItem in soundItems) if (s.soundName==what) return s;
			return null;
		}
		
		//
		public function playRandomSound (fromWhere:String, loop:Boolean=false, offset:Number=0):SoundChannel {
			var myList:Array = this[fromWhere+"Names"];
			return playSound(myList[Math.floor(Math.random()*myList.length)], loop, offset);
		}
		
		//
		public function onSoundComplete (e:AudioEvent):void {
			if (e.name.indexOf("section_3_lane_vibrate")>-1){
				if(arrowOver){
					getInstance("section_3_lane_vibrate").start();
				} else {
					arrowSoundPlaying = false
				}
			}
			/*
			if (e.name.indexOf("drum_loop_")>-1 && arrowOver) return//startArrowLoop();//Pete's dirty work!
			
			if (e.name.indexOf("drum_loop_")>-1 && !arrowOver && arrowSoundIndex>=0) {
				arrowSoundsItems[arrowSoundIndex + (NUM_ARROW_SOUNDS*2)].start();
				arrowSoundPlaying = false;
			}
			*/
			
		}
		
		//
		public function onSoundLoaded (e:AudioEvent):void {
			doOutput("loaded: "+e.name);
			if (e.name==padsNames[3]) dispatchEvent(new AudioEvent(AudioEvent.READY));
			// 3 is one bgpad for each section and one extra from the first section :D
			// if (e.name == loadingItem) loadNextItem(); // e.name.indexOf(loadingItem)>-1
			loadNextItem();
		}
		
		//
		public function startPadSound (e:Event=null, section:Number=-1):void {
			if (section>-1) currentSoundScape = section;
			var sIndex:Number;
			var myItem:SoundItem;
			var isLoaded:Boolean = false;
			while (!isLoaded) {
				sIndex = Math.floor(Math.random()*numPads);
				sIndex *= numSoundScapes;
				sIndex += currentSoundScape;
				myItem = SoundItem(padsItems[sIndex]);
				if (myItem && myItem.length) isLoaded = true;
			}
			var loopTime:Number = myItem.length-CROSSFADE < 0 ? myItem.length*.9 : myItem.length-CROSSFADE;
			var t:Timer = new Timer(loopTime, 1);
			t.addEventListener(TimerEvent.TIMER, startPadSound);
			t.start();
			myItem.start();
			doOutput("# pad length: "+(Math.round(myItem.length)/1000)+" secs");
		}
		
		//
		
		public function arrowRollOver (e:Event):void {
			return
			//
		}
		
		public function LaneRollOver ():void {
			arrowOver = true;
			startLaneSound();
		}
		
		public function LaneRollOut():void {
			arrowOver = false;
		}
		
		//
		public function startLaneSound ():void {
			if (arrowSoundPlaying) return;
			arrowSoundPlaying = true;
			getInstance("section_3_lane_vibrate").start();
		}
		
		//
		public function startArrowLoop (e:Event=null, section:Number=-1):void {
			if(!arrowOver && arrowSoundIndex) {
				arrowSoundsItems[arrowSoundIndex + (NUM_ARROW_SOUNDS*2)].start();
				return;
			}
			arrowSoundIndex = Math.floor(Math.random() * NUM_ARROW_SOUNDS);
			arrowSoundsItems[arrowSoundIndex + NUM_ARROW_SOUNDS].start(false, LOOP_CUT);
			arrowSoundPlaying = true;
			
			var t:Timer = new Timer(arrowSoundsItems[arrowSoundIndex + NUM_ARROW_SOUNDS].length-_mp3offset, 1);
			t.addEventListener(TimerEvent.TIMER, startArrowLoop);
			t.start();
		}
		//
		public function arrowRollOut (e:Event):void {
			//arrowOver = false;
		}
		
		// Outputs debug messages
		public function doOutput (msg:String):void {
			if (!output) return;
			output.appendText(msg + "\n");
			output.scrollV = output.maxScrollV;
		}
		
		public function toggleMute (force:*=null):Boolean {
			if (force!=null && typeof force != "boolean") return isMuted;
			isMuted = force==null ? !isMuted : force;
			return isMuted;
		}
		
		public function get isMuted ():Boolean { return _isMuted };
		public function set isMuted (value:Boolean):void {
			_isMuted = value;
			for each (var s:SoundItem in soundItems) s.isMuted = value;
		}
		
		public function set mp3offset(value:Number):void {
			_mp3offset = value
			for each (var s:SoundItem in soundItems) s.mp3offset = value;
		}
		
	}
	
}